//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "LF2_Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TmyForm *myForm;
//---------------------------------------------------------------------------
__fastcall TmyForm::TmyForm(TComponent* Owner)
  : TForm(Owner)
{
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::OpenBinaryTextData1Click(TObject *Sender)
{
  char buf[256],
       *p;
  FILE *tf;

  Open1->Filter     = "SNES ROM | *.s*c; *.fig;";
  Open1->InitialDir = cur_dir;
  //
  if ( Open1->Execute( ) )
  { // Create Dump directory!
    getcwd( dirc, MAXPATH );
    strcat( dirc, "\\Dumps" );
    mkdir( dirc );

    //
    strcpy(romf, Open1->FileName.c_str( ) );
    tf = fopen( romf, "rb" );
    if ( !tf ){
      ShowMessage("Fatal Error: Could not open file!");
      return;
    }
    //
    _free( rom.data );
    rom.data = (BYTE *)malloc( rom.Length = FileSize( tf ) );
    //
    if ( !rom.data ){
      fclose( tf );
      ShowMessage( "Fatal Error: Could not allocate needed memory!" );
      Close( );
    }

    // Check for dumb header
    if ( rom.Length & 0x0200 ){
//      rom.Length -= 0x0200;
      rom.Header  = 0x0200;
//      fseek( tf, 0x0200, SEEK_SET );
    }
    // Read in the data
    fread( rom.data, 1, rom.Length, tf );
    rom.data += rom.Header;
    fclose( tf );
    //
//    intxt.rom = rom.data;
    //---------------------------------//
    // Make sure it's Light Fanstasy 2 //
    //---------------------------------//
    if ( strncmp( &rom.data[0x1747A], "Light Fantasy 2 95/08/10", 24 ) ){
      ShowMessage("Error: This is not the ROM used.\n"
                  "Please load the correct ROM."
                 );
      _free( rom.data );
      return;
    }
    //
//    ShowMessage( "ROM Loaded successfully!" );
    LoadDataFileClick( Sender );
    //
    if ( cmForm->bList->Items->Count <= 0 ) return;
    cmForm->bList->ItemIndex = 0;
    if ( cmForm->Visible ) cmForm->bList->SetFocus( );
    bListClick( NULL );
    //
    iCanDraw = true;
  }
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::SaveTextFile1Click(TObject *Sender)
{
  TxtForm->TDMemo->Lines->SaveToFile( AnsiString( txtf ) );
  ShowMessage( "\"" + AnsiString( ExtractFileName(txtf) ) + "\" was saved successfully!" );
  TxtForm->TDMemo->Modified = false;
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::Exit1Click(TObject *Sender)
{
  int k;

  if ( TxtForm->TDMemo->Modified ){
    k = Application->MessageBox(
          "Current text file modified. Want to save this file?", "File Modified...",
          MB_ICONQUESTION + MB_YESNO
        );
    //
    if ( k == ID_YES )
      SaveTextFile1Click( NULL );
  }
  //
  Close( );
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::bListClick(TObject *Sender)
{
  FILE *df;
  long valu;
  char buf[256],
       *p;

  for ( int i = 0; i < cmForm->bList->Items->Count; i++ )
  { //
    if ( cmForm->bList->Selected[ i ] )
    {
//      strcpy( buf, cmForm->bList->Items->Strings[ i ].c_str( ) );
      txt.posi       = i; //strtoul( p, NULL, 16 );
      //
//      txt.pntr       = WGET( rom.data, Snes2Pc(txt.posi) );
      txt.pntr       = WGET( rom.data, Snes2Pc(lpTxtBlocks[ i ]) );
      txt.Max_ptrs   = (txt.pntr - (lpTxtBlocks[ i ] & 0xFFFF)) & 0x0FFF;
      txt.Max_ptrs >>= 1;
      // File the list box with data
      cmForm->pList->Clear( );
      for ( int c = 0; c < txt.Max_ptrs; c++ )
      {
        sprintf( buf, "String# %-5d", c );
        cmForm->pList->Items->Add( AnsiString( buf ) );
        lpTxtPoints[ c ] = WGET( rom.data, Snes2Pc(lpTxtBlocks[ i ] + (c << 1)) );
      }
      //------------------------//
      // Get new text file data //
      //------------------------//
//      sprintf( buf, "%s/Block_%02d.txt", dirc, i );
      sprintf( buf, "%s\\%08X.txt", dirc, lpTxtBlocks[ txt.posi ] );
      if ( FileExists( AnsiString( txtf ) ) )
      { //
        if ( TxtForm->TDMemo->Modified ){
           int k = Application->MessageBox(
             "Current data not saved. Do you wish to save it?",
             "File Modified...",
             MB_ICONQUESTION + MB_YESNO
           );
           // If yes, save the file
           if ( k == ID_YES )
             SaveTextFile1Click( NULL );
        }
      }
      // Load new data
      strcpy( txtf, buf );
      if ( FileExists( AnsiString( txtf ) ) )
        TxtForm->TDMemo->Lines->LoadFromFile( AnsiString(txtf) );
      else
      { // Create the dump Data
        df = fopen( buf, "wt" );
        if ( df )
        { //
          fprintf( df, "// Do not erase these: \n// .STRING #\n// .ENDS\n\n\n" );
          for ( int c = 0; c < txt.Max_ptrs; c++ )
            fprintf( df, ".STRING %d\n\n\n\n.ENDS\n\n\n\n", c );

          // Close the file
          fclose( df );
        }// END IF - df
      }

      //
      txt.ptr_posi             = 0;
      cmForm->pList->ItemIndex = 0;
      cur_str                  = 0;

      cmForm->pList->Hint      = IntToStr( cmForm->pList->Items->Count ) + " item(s)";
      pListClick( NULL );
      if ( cmForm->Visible ) cmForm->bList->SetFocus( );
      TxtForm->TDMemo->Modified = false;
    }// NEXT
  }
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::LoadDataFileClick(TObject *Sender)
{
  LONG x,y,z;
  int  cpos;
  CODE *tcode = NULL;
  char buf[560],
       cuf[560],
       arg1[32],
       arg2[32],
       var[16],
      *p;
  FILE *tf,
       *df;

  Open1->Title      = "Open Text Block Data File";
  Open1->Filter     = "Font Format File | *.txt";
  Open1->InitialDir = cur_dir;
  Open1->FileName   = "";
  //
  if ( Open1->Execute( ) )
  { //
    tf = fopen( Open1->FileName.c_str( ), "rt" );
    if ( !tf ){
      ShowMessage("Fatal Error: Could not open FONT file!");
      return;
    }

    iCanDraw  = false;
    // Release the last codes loaded
    for ( int c = 0; c < 0x10000; c++ ){
      _free( codes[c / 256].text );
      _free( duals[ c].text );
      codes[c / 256].color  = 0x0E;
      duals[ c ].color      = 0x0D;
      codes[ c / 256 ].type = 0;
      duals[ c ].type       = 0;
    }

    memset(buf, 0, 256);
    cmForm->bList->Clear( );
    cpos = 0;

    // get the format data
    while( fgets( buf, 256, tf ) )
    { //----------------------//
      // Textbox color data   //
      //----------------------//
      if ( !strncmpi(buf, ".textbox", 8) )
      { //
        sscanf( buf, "%s %s", &cuf, &arg1 );
        // Get the color
        if ( strstr( buf, ".color.blue") ) Blue1->Checked   = true;
        if ( strstr( buf, ".color.green")) Green1->Checked = true;
        if ( strstr( buf, ".color.red")  ) Red1->Checked   = true;
        // Get the color type
        if ( strstr( buf, ".solid" ) )     Solid1->Checked = true;
        if ( strstr( buf, ".gradient"))    Gradient1->Checked = true;
      }

      //----------------------//
      //                      //
      //----------------------//
      if ( !strncmpi(buf, ".Font", 5) )
      {
        sscanf( buf, "%s %X", &cuf, &map.lpFontOffset );
      }
/*      //
      if ( !strncmpi(buf, ".TransText", 10) )
      {
        sscanf( buf, "%s %s", &cuf, &cuf );
        if ( !strcmpi( cuf, "SHOW" ) ){
          DTT->Checked = false;
          DTTClick( Sender );
        }
      }
*/
      //----------------------//
      //                      //
      //----------------------//
      if ( !strncmpi(buf, ".CONTROLCODES", 13) )
      {
        sscanf( buf, "%s %s", &cuf, &cuf );
        if ( !strcmpi( cuf, "HIDE" ) ) HideCodes->Checked = false; else HideCodes->Checked = true;
        HideCodesClick( Sender );
      }
      //----------------------//
      //                      //
      //----------------------//
      if ( !strncmpi(buf, ".VWF", 4) )
      {
        sscanf( buf, "%s %s", &cuf, &cuf );
        if ( !strcmpi( cuf, "ON" ) ) UseVWFRoutine1->Checked = false; else UseVWFRoutine1->Checked = true;
        UseVWFRoutine1Click( Sender );
      }

      //----------------------//
      //                      //
      //----------------------//
      if ( !strncmpi(buf, ".TextWindow", 11) )
      {
        sscanf( buf, "%s %s", &cuf, &cuf );
        if ( !strcmpi( cuf, "hide" ) ) TxtForm->Visible = false; else TxtForm->Visible = true;
      }

      //----------------------//
      //                      //
      //----------------------//
      if ( !strncmpi(buf, ".HexWindow", 10) )
      {
        sscanf( buf, "%s %s", &cuf, &cuf );
        if ( !strcmpi( cuf, "hide" ) ) HexForm->Visible = false; else HexForm->Visible = true;
      }
      //----------------------//
      //                      //
      //----------------------//
      if ( !strncmpi(buf, ".KanaWindow", 11) )
      {
        sscanf( buf, "%s %s", &cuf, &cuf );
        if ( !strcmpi( cuf, "hide" ) ) KanaForm->Visible = false; else KanaForm->Visible = true;
      }

      //----------------------//
      //                      //
      //----------------------//
      if ( !strncmpi(buf, ".FORMAT", 7) )
      { // goto _ReadGood;
        sscanf( buf, "%s   %d    %d  %d  %d   %d   %d %d %d %d",
                &buf[128],
                &map.cpl,
                &map.height,
                &map.width,
                &map.bpp,
                &map.inc,
                &map.set[0], &map.set[1],
                &map.set[2], &map.set[3]
              );
        //
        map.cpl *= map.inc;
      }

      //
      if ( !strncmpi(buf, ".BLOCK", 6) )
      { //
        x = y = z = 0;
        sscanf( buf, "%s %X %X %X", &cuf, &x, &y, &z );
        //
        sprintf( buf, "Block %X", x );
        //
        lpTxtBlocks[ cpos ] = x;
        lpTextStart[ cpos ] = y;
        lpTxtPoints[ cpos ] = 0;
        lpTxtMaxPos[ cpos ] = z;
        cpos++;
        //
        cmForm->bList->Items->Add( buf );
      }
      //---------------------------------------//
      // Check for color able index assignment //
      //---------------------------------------//
      if ( !strncmpi( buf, ".COLORTABLE", 6 ) )
      { //
        while( fgets( buf, 256, tf ) )
        { // Load the text value
          if ( !(x = strncmpi( buf, ".NULL=", 6)) || !(y = strncmpi( buf, ".NULL16", 7)) )
          {
            p = strchr( buf, '=' );
            if ( !p ) continue;
            *p = ' ';
            sscanf( buf, "%s %s", &cuf, &arg1 );
            //
            if ( !y ){
              // DUALS
              for ( int c = 0; c < 0x10000; c++ )
                if ( duals[c].type ) duals[c].color = GetIndex( arg1 );
            } else {
              // CODES
              for ( int c = 0; c < 0x00100; c++ )
                if ( codes[c].type ) codes[c].color = GetIndex( arg1 );
            }
          }
          else
          //----------------------------------//
          // Standard colors for table values //
          //----------------------------------//
          if ( p = strchr( buf, '=' ) )
          { //
            *p = ' ';
            z = (LONG)p - (LONG)buf;
            sscanf( buf, "%X %s", &x, &arg1 );
            //
            if ( z > 2 )
              tcode = &duals[x];
            else
              tcode = &codes[x];
            //
            tcode->color = GetIndex( arg1 );
          }
          else
          if ( strstr( buf, ".ENDCOLOR" ) )
            break;
          // end if
        }
      }
      //-------------------------//
      // Load up table file data //
      //-------------------------//
      if ( !strncmpi( buf, ".TABLE", 6 ) )
      { //
        while( fgets( buf, 256, tf ) )
        { // Load the text value
          if ( !(x = strncmpi( buf, ".NULL ", 6)) || !(y = strncmpi( buf, ".NULL16", 7)) )
          { //
            sscanf( buf, "%s %s %s %s", &cuf, &arg1, &cuf, &arg2 );
            //
            int  min = GetIndex( arg1 ),
                 max = GetIndex( arg2 );
            //
            if ( min > max ){
              x   = min;
              min = max;
              max = x;
            }
            //
            for ( int c = min; c <= max; c++ )
            { //
              tcode = ( (!x) ? &codes[c] : &duals[c] );
              //
              tcode->text = (BYTE *)malloc( 6 );
              if ( !tcode->text ){
                ShowMessage( "Error: Program outof memory. 'TABLE DATA Load'. " );
                fcloseall( ); Close( ); return;
              }
              //
              sprintf( tcode->text, "[$%02X]", c );
              tcode->type = 1;  // Make this a NULL code
            }

          }
          else
          if ( p = strchr( buf, '=' ) )
          { //
            *p = ' ';
            z = (LONG)p - (LONG)buf;
            //
            memset( cuf, 0, 256 );
            sscanf( buf, "%X %s", &x, &cuf );
            if ( z > 2 )
              tcode = &duals[x];
            else
              tcode = &codes[x];
            //
            tcode->length = strlen( cuf );
            memset( buf, 0, 256 );
            // Format string and get length
            if ( strstr( cuf, "\\x" ) )
            { //
              tcode->length = 0;
              for ( int c = 0; c < strlen( cuf ); c++ )
              { //
                if ( cuf[ c ] == '\\' && cuf[ c + 1 ] == 'x' )
                { //
                  c += 2;
                  memset( var, 0, 16 );
                  var[ 0 ] = cuf[ c++ ];
                  var[ 1 ] = cuf[ c++ ];
                  //
                  buf[ tcode->length++ ] = strtoul( var, NULL, 16 );
                }
                else
                  buf[ tcode->length++ ] = cuf[ c ];
                //
              }
              //
              memset( cuf, 0, 256 );
              memcpy( cuf, buf, tcode->length + 1 );
            }
            //
            // Set the End of text BYTE
//            cuf[ tcode->length ] = 0xFF;
            tcode->text = (BYTE *)malloc( tcode->length + 1 );
            //
            if ( !tcode->text ){
              ShowMessage( "Error: Program outof memory. 'TABLE DATA Load'. " );
              fcloseall( ); Close( ); return;
            }
            //
            memcpy( tcode->text, cuf, tcode->length + 1 );
            //----------------------//
            // This means it's NULL //
            //----------------------//
            if ( !tcode->length )
            { //
              _free( tcode->text );
              tcode->text = (BYTE *)malloc( 6 );
              if ( !tcode->text ){
                ShowMessage( "Error: Program outof memory. 'TABLE DATA Load'. " );
                fcloseall( ); Close( ); return;
              }
              //
              sprintf( tcode->text, "[$%02X]", x );
              tcode->type = 1;  // Make this a NULL code
            }
          }
          else
          if ( strstr( buf, ".ENDTABLE" ) )
            break;
          // end if
        }
      }
    }
    // Load all block data
    fclose( tf );
    iCanDraw = true;
    //
    myForm->Caption = "Script Editor: Light Fantasy 2 - [ " + ExtractFileName( Open1->FileName ) + " ]";
     // Init the first block
    cmForm->bList->ItemIndex = 0;
    cmForm->bList->Hint = IntToStr( cmForm->bList->Items->Count ) + " item(s)";
    bListClick( NULL );
    //
//    DrawText( false, map.height, map.width, map.lpFontOffset );
  }
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::FormCreate(TObject *Sender)
{
  WORD *VRAM;

  getcwd( cur_dir, MAXPATH );
  Open1->InitialDir = cur_dir;

  Vga = new Graphics::TBitmap;
  //
  if ( !Vga ){
    ShowMessage("Fatal Error: Could not acquire Video Pointer." );
    Close( );
    return;
  }

  Vga->Width       = Video->Width;
  Vga->Height      = Video->Height;
  Vga->PixelFormat = pf16bit;
  //
  txt.posi  = 0;
  txt.index = 0;
  //

  ScrBuf         = (WORD *)malloc( (Vga->Width * Vga->Height) << 2 );
  textbox[0].pic = (WORD *)malloc( (0x39000 << 2) );
  textbox[1].pic = (WORD *)malloc( (0x39000 << 2) );
  //
  lpTxtBlocks = (LONG *)malloc( TEXT_ENTRIES * sizeof(LONG) );
  lpTxtPoints = (LONG *)malloc( TEXT_ENTRIES * sizeof(LONG) );
  lpTextStart = (LONG *)malloc( TEXT_ENTRIES * sizeof(LONG) );
  lpTxtMaxPos = (LONG *)malloc( TEXT_ENTRIES * sizeof(LONG) );
  //
  ram  = (BYTE *)malloc( 0x20000 );
  EStr = (BYTE *)malloc( 0x20000 );
  if ( !ram || !ScrBuf || !textbox[0].pic ||
       !textbox[1].pic || !EStr ||
       !lpTxtBlocks || !lpTxtPoints ||
       !lpTextStart || !lpTxtMaxPos
  ){
    ShowMessage("Fatal Error: Could not allocate memory!" );
    myForm->Close( );
    return;
  }

  //
  memsetw( ScrBuf, 0x0000, Vga->Width * Vga->Height );
  memset( ram , 0, 0x20000 );
  memset( EStr, 0, 0x20000 );
  textbox[0].height = 0x0300;
  textbox[1].height = 0x0300;
  //
  WinX = myForm->ClientWidth;
  WinY = myForm->ClientHeight;
  // Assign default colors to codes
  for ( int c = 0; c < 0x10000; c++ )
    codes[(c / 256)].color =
    duals[ c ].color       = 15;
  //
  for ( int y = 0; y < Vga->Height; y++ )
  { //
    (void *)VRAM = Vga->ScanLine[ y ];
      memset( VRAM, 0, Vga->Width << 1);
  }
  //
  Video->Canvas->StretchDraw( Video->ClientRect, Vga );

  iCanDraw = false;
  isActive = true;
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::FormClose(TObject *Sender, TCloseAction &Action)
{
  int  k;

  if ( TxtForm && TxtForm->TDMemo->Modified )
  { //
    k = Application->MessageBox(
      "TEXT data not saved. Do you wish to save it?",
      "TEXT File Modified...",
      MB_ICONQUESTION + MB_YESNO
    );
    // If yes, save the file
    if ( k == ID_YES )
      SaveTextFile1Click( NULL );
  }
  //
  if ( rom.Modified )
  { //
    k = Application->MessageBox(
      "ROM data modified. Do you wish to save changes?",
      "ROM File Modified...",
      MB_ICONQUESTION + MB_YESNO
    );
    // If yes, save the file
    if ( k == ID_YES )
      SaveRomFile1Click( NULL );
  }

  _free( rom.data );
  _free( ram );
  _free( EStr );
  _free( ScrBuf );
  _free( textbox[0].pic );
  _free( textbox[1].pic );
  //
  _free( lpTxtBlocks );
  _free( lpTxtPoints );
  _free( lpTxtMaxPos );
  _free( lpTextStart );
  //
  for ( int c = 0; c < 0x10000; c++ ){
    _free( duals[c].text );
    _free( codes[c/256].text );
  }

  isActive = false;

  if ( Vga ) delete Vga;
  if ( HexForm && HexForm->PIC ) delete HexForm->PIC;
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::DrawText( bool skip, int height, int width )
{
  #define StartX     0
  #define StartY     0
  #define MASK_COLOR 0x11
  #define NONTEXT    0x0A
  #define NONTEXT2   0x0C
  #define NONTEXT3   0x04

  LONG tilep;
  char buf[256];
  WORD *VRAM;
  static TBOX *myBox;
  BYTE *TEMP    = NULL,
       COLR,
       TCOLR,
       BITS,
       BUFR[256],
       TILE[16][16],
       flag = 0,
       VWF;

  // Make sure we can do this!
  if ( !rom.data || !ram || !iCanDraw ) return;

  if ( !skip )
  { // Get the Text pointer and display the text!
    myBox      = &textbox[ (int)DTT->Checked ];
    memsetw( myBox->pic, 0, 0x39000 );
    memset( &men, 0, sizeof(TMEN) );
    //
    txt.tColor = 15;
    txt.data   = 0;
    men.Ypos   = 0;
    men.Xpos   = 0;
    // Select which text box to use
    txt.xpos   = StartX;
    txt.ypos   = StartY;
    if ( !DTT->Checked ) memsetw( ScrBuf, 0, (Vga->Width * Vga->Height) );
    //----------------------------//
    // Check to see if we use the //
    // ROM or the buffer          //
    //----------------------------//
    if ( DTT->Checked )
    { //
      txt.TextBuf  = EStr;
      men.Xdim     = 224 >> 3;
      myBox->width = men.Xdim << 3;
      flag         = 1;
    }
    else
    { //
      txt.pntr     = lpTxtPoints[ txt.ptr_index ];
      txt.TextBuf  = &rom.data[ Snes2Pc( (lpTxtBlocks[ txt.posi ] & 0xFF8000) | txt.pntr) ];
      map.cpl      = (38 << 3);
      men.Xdim     = map.cpl >> 3;
      myBox->width = men.Xdim << 3;
      flag         = 0;
    }
    //
    if ( !DTT->Checked ){
      // Draw the hex data
      HexForm->DrawHex( txt.TextBuf, flag );
      // Dump the text to the string viewer
      KanaForm->ShowText( txt.TextBuf, flag );
    }
  }

  //------------------------------------//
  // Display the text data              //
  //------------------------------------//
  while( txt.data != 0xFF )
  { //
    txt.data     = txt.TextBuf[0];
    txt.TextBuf += 1;

    //-------------//
    // Kanji       //
    //-------------//
    if ( (txt.data & 0xF0 ) == 0xE0 ) {
      txt.data     = ((txt.data & 0x0F) << 8) + txt.TextBuf[0];
      txt.data += 0x00E0;
      txt.TextBuf += 1;
    } else
    //-------------//
    // Compression //
    //-------------//
    if ( txt.data >= 0xF0 && txt.data <= 0xF3 )
    { //
      txt.data     = txt.TextBuf[0] + ( (txt.data & 0x03) << 8 );
      txt.TextBuf += 1;
      //
      TEMP        = txt.TextBuf;
      txt.data    = WGET( rom.data, Snes2Pc( 0x8FF900 + ( txt.data << 1)) );
      txt.TextBuf = &rom.data[ Snes2Pc( 0x8F0000 + txt.data ) ];
      COLR        = txt.tColor;
      txt.tColor  = 14;
      //
      DrawText( true, map.height, map.width );
      // Restore color
      txt.tColor  = COLR;
      txt.TextBuf = TEMP;
      TEMP        = NULL;
      txt.data    = 0;
      continue;
    } else
    //------------------//
    // Item from memory //
    //------------------//
    if ( txt.data == 0xF4 ){
      txt.data     = txt.TextBuf[0];
      txt.TextBuf += 1;
      //
      TEMP        = txt.TextBuf;
      COLR        = txt.tColor;
      txt.tColor  = NONTEXT;
      sprintf( buf, "[Name$%02X]\xff", txt.data );
      txt.TextBuf = buf;
      //
      DrawText( true, 16, 8 );
      txt.tColor  = COLR;
      txt.TextBuf = TEMP;
      TEMP        = NULL;
      txt.data    = 0;
      continue;
    } else
    //----------------//
    // Clear Screen   //
    //----------------//
    if ( txt.data == 0xF5 ) {
      if ( HideCodes->Checked ){
        txt.data = 0;
        continue;
      }
      //
      TEMP        = txt.TextBuf;
      COLR        = txt.tColor;
      txt.tColor  = NONTEXT2;
      sprintf( buf, "[ClrScr]\xff" );
      txt.TextBuf = buf;
      //
      DrawText( true, 16, 8 );
      txt.tColor  = COLR;
      txt.TextBuf = TEMP;
      TEMP        = NULL;
      txt.data    = 0;
      continue;
    } else
    //----------------//
    // Unknowm        //
    //----------------//
    if ( txt.data == 0xFA ) {
      txt.data     = txt.TextBuf[0] + (txt.data << 8);
      txt.TextBuf += 1;
      if ( HideCodes->Checked ){
        txt.data = 0;
        continue;
      }
      //
      TEMP        = txt.TextBuf;
      COLR        = txt.tColor;
      txt.tColor  = NONTEXT2;
      sprintf( buf, "[$%04X]\xff", txt.data );
      txt.TextBuf = buf;
      //
      DrawText( true, 16, 8 );
      txt.tColor  = COLR;
      txt.TextBuf = TEMP;
      TEMP        = NULL;
      txt.data    = 0;
      continue;
    } else
    //-------------//
    // KeyPress    //
    //-------------//
    if ( txt.data == 0xF6 ){
      if ( HideCodes->Checked ){
        txt.data = 0;
        continue;
      }
      //
      TEMP        = txt.TextBuf;
      COLR        = txt.tColor;
      txt.tColor  = NONTEXT3;
      sprintf( buf, "[Key]\xff", txt.data );
      txt.TextBuf = buf;
      //
      DrawText( true, 16, 8 );
      txt.tColor  = COLR;
      txt.TextBuf = TEMP;
      TEMP        = NULL;
      txt.data    = 0;
      continue;
    } else
    //-------------//
    // Text Color  //
    //-------------//
    if ( txt.data == 0xF7 ){
      txt.data     = txt.TextBuf[0];
      txt.TextBuf += 1;
      if ( HideCodes->Checked ){
        txt.data = 0;
        continue;
      }
      //
      TEMP        = txt.TextBuf;
      COLR        = txt.tColor;
      txt.tColor  = NONTEXT2;
      sprintf( buf, "[Color$%02X]\xff", txt.data );
      txt.TextBuf = buf;
      //
      DrawText( true, 16, 8 );
      txt.tColor  = COLR;
      txt.TextBuf = TEMP;
      TEMP        = NULL;

      txt.data    = 0;
      continue;
    } else
    //-------------//
    // Text Speed  //
    //-------------//
    if ( txt.data == 0xF8 ){
      COLR        = txt.tColor;
      //
      txt.data     = txt.TextBuf[0];
      txt.TextBuf += 1;
      //
      if ( HideCodes->Checked ){
        txt.data = 0;
        continue;
      }
      //
      TEMP         = txt.TextBuf;
      //
      txt.tColor  = NONTEXT2;
//      sprintf( buf, "[$F8%02X]\xff", txt.data );
      sprintf( buf, "[Pause$%02X]\xff", txt.data );
      txt.TextBuf = buf;
      //
      DrawText( true, 16, 8 );
      txt.tColor  = COLR;
      txt.TextBuf = TEMP;
      TEMP        = NULL;
      txt.data    = 0;
      continue;
    } else
    //-----------------------//
    // Unknown               /
    //-----------------------//
    if ( txt.data == 0xF9 || txt.data == 0xFB ||
         txt.data == 0xFC //|| txt.data == 0xFD
       )
    {
      if ( HideCodes->Checked ){
        txt.data = 0;
        continue;
      }
      //
      COLR        = txt.tColor;
      txt.tColor  = NONTEXT2;
      sprintf( buf, "[$%02X]\xff", txt.data );
      TEMP        = txt.TextBuf;
      txt.TextBuf = buf;
      DrawText( true, 16, 8 );
      txt.TextBuf = TEMP;
      TEMP        = NULL;
      txt.tColor  = COLR;
      txt.data    = 0;
      continue;
    } else
    //----------------//
    // Make Selection //
    //----------------//
    if ( txt.data == 0xFD ){
      if ( HideCodes->Checked ){
        txt.data = 0;
        continue;
      }
      //
      COLR        = txt.tColor;
      txt.tColor  = NONTEXT3;
      sprintf( buf, "[Choice]\xff" );
      TEMP        = txt.TextBuf;
      txt.TextBuf = buf;
      //
      DrawText( true, 16, 8 );
      txt.TextBuf = TEMP;
      TEMP        = NULL;
      txt.tColor  = COLR;
      txt.data    = 0;
      continue;
    } else
    //-------------//
    // Line Break; //
    //-------------//
    if ( txt.data == 0xFE ){
      txt.data  = 0;
      txt.ypos += height;
      txt.xpos  = StartX;
      men.Ydim += 2;
      continue;
    } else
    //-------------//
    // End Text    //
    //-------------//
    if ( txt.data == 0xFF ){
      txt.data = 0;
      if ( skip ) return;
      break;
    }//*/

    //-----------------------------//
    // Font size testing done here //
    //-----------------------------//
//    if ( height == 16 && width == 16 )
    if ( (height == map.height && width == map.width) && !DTT->Checked )
    { //
      // Display the text
      txt.tpos = txt.data;
      txt.tpos = WGET( rom.data, Snes2Pc( 0x8C9C00 + (txt.data << 1)) );
      //
      DecodeFont( Snes2Pc( 0x8C0000 + txt.tpos ), BUFR );
      // Convert the tile data
      int x = -1;
      while( ++x < 8 ){
        Dec2Bin( &txt.tile[ (x + 0x00) << 4 ], (BUFR[ x + 0x00 ] << 8) + BUFR[ x + 0x08], 16 );
        Dec2Bin( &txt.tile[ (x + 0x08) << 4 ], (BUFR[ x + 0x10 ] << 8) + BUFR[ x + 0x18], 16 );
      }
      //
    }
    else
    if ( ((height == map.height && width == width) && DTT->Checked) && !skip )
    { // Last Transfer
      memcpy( BUFR, &FONT16x16[ (txt.data & 0xFF) << 5 ], 0x20 );
      memset( txt.tile, 0, 256 );
      // Convert the tile data
      int x = -1;
      while( ++x < 16 )
        Dec2Bin( &txt.tile[ x << 4 ], (BUFR[ x ] << 8) + BUFR[ x + 0x10 ], 16 );
      //
    }
    else
    {
      memcpy( BUFR, &FONT8x16[ (txt.data & 0xFF) << 4 ], 0x10 );
      memset( txt.tile, 0, 256 );
      // Convert the tile data
      int x = -1;
      while( ++x < 16 )
        Dec2Bin( &txt.tile[ x << 3 ], BUFR[ x ], 8 );
      //
    }

    //---------------//
    // DMA to Vram   //
    //---------------//
    VWF       = 0;
    txt.ypos %= myBox->height;
    //
    for ( int y = 0; y < height; y++ )
    { //
      for ( int x = 0; x < width; x++ )
      { //
        if ( txt.tile[ (y * width) + x ] )
        { // Add pixel
          myBox->pic[ ((txt.ypos + y) * myBox->width) + (txt.xpos + x + 0) ]     = DOS565[ txt.tColor ];
          // Add Shadow on the side
          myBox->pic[ ((txt.ypos + y) * myBox->width) + (txt.xpos + x + 1) ]     = DOS565[ MASK_COLOR ];
          // Add Shadow on the bottom + side
//          myBox->pic[ ((txt.ypos + y + 1) * myBox->width) + (txt.xpos + x + 1) ] = DOS565[ MASK_COLOR ];
          // For VWF routine
          if ( x > VWF ) VWF = x;
          // For some reason single pixel
          // fonts don't record a value
          if ( !VWF ) VWF = 1;
        }
        else
        { //
          if ( myBox->pic[ ((txt.ypos + y) * myBox->width) + (txt.xpos + x + 0) ] != DOS565[ MASK_COLOR ] )
            myBox->pic[ ((txt.ypos + y) * myBox->width) + (txt.xpos + x + 0) ] = DOS565[ 0 ];
        }
        //
      }
    }// NEXT y

    //
//    txt.xpos += ( (width == map.width) ? map.inc : width );
//    if ( UseVWFRoutine1->Checked ){
    if ( UseVWFRoutine1->Checked || DTT->Checked ){
      if ( !VWF && BITS ) VWF = 1;
      if ( !VWF ) VWF = 4;
      txt.xpos += VWF + 2;
    } else
      txt.xpos += ( (width == map.width) ? map.inc : 5 );

    // Check Width boundaries for NON-English
    if ( (!DTT->Checked && (txt.xpos >= map.cpl)) ){
      txt.xpos  = StartX;
      txt.ypos += height;
      men.Ydim += 2;
    }

    // Check Width boundaries for NON-English
    if ( DTT->Checked && txt.xpos >= ((men.Xdim << 3) - 24) ){
      txt.xpos  = StartX;
      txt.ypos += height;
      men.Ydim += 2;
    }
  }

  // Build Map, Draw the MenuMap, masking enabled
  men.Ydim                = 14;
  men.menu[0][0]          = 1;
  men.menu[0][men.Xdim-1] = 3;
  memset( &men.menu[0][1], 2, men.Xdim - 2 );
  //
  men.menu[men.Ydim-1][0]        = 6;
  men.menu[men.Ydim-1][men.Xdim-1] = 8;
  memset( &men.menu[men.Ydim-1][1], 7, men.Xdim - 2 );
  //
  for ( int y = 1; y < men.Ydim-1; y++ )
  { //
    men.menu[y][0]        = 4;
    men.menu[y][men.Xdim-1] = 5;
  }
  //-----------------------------//
  // Which box to draw & display //
  //-----------------------------//
  if ( !DTT->Checked )
    MenuMap( &ScrBuf[(0x08 * Vga->Width) + 8], &men, Vga->Width, 0 );
  else
    MenuMap( &ScrBuf[(0x88 * Vga->Width) + 8], &men, Vga->Width, 0 );
  //
  myBox->Xpos = (DTT->Checked ? 0x88 : 0x08);
  //
  int  ypos = (DTT->Checked ? 0x88 : 0x08);
  for ( int y = 0; y < ((men.Ydim+0) << 3); y++ )
  { //
    (void *)VRAM = Vga->ScanLine[ y + myBox->Xpos ];
     memcpyw( VRAM, &ScrBuf[ (y + ypos) * Vga->Width ], Vga->Width, 0 );
  }// NEXT y

  //
  myBox->Xpos = (DTT->Checked ? 0x90 : 0x10);
  //
  for ( int y = 0; y < 96; y++ )
  { //
    (void *)VRAM = Vga->ScanLine[ (y + myBox->Xpos) ];
     // Draw the Text data
     memcpyw( &VRAM[16], &myBox->pic[ ((y + myBox->Ypos) * myBox->width) ], myBox->width, 2 );
  }// NEXT y

  Video->Canvas->StretchDraw( Video->ClientRect, Vga );
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::pListClick(TObject *Sender)
{
  #define LINE_BREAK 0xFE
  #define TEXT_BREAK 0xFF
  #define STRING_END 0x00

  long valu,
       pos;
  WORD inPosi,
       sLen;
  char buf[256],
       tuf[256];
  char conv[16],
       flag,
       c_test,
       *p1,
       *p2;
  char *codes [ ] =
  {
    "NAME"  , "\xF4",
    "CLRSCR", "\xF5",
    "KEY"   , "\xF6",
    "COLOR" , "\xF7",
    "PAUSE" , "\xF8",
    "CHOICE", "\xFD",
    "\0"    , "\0"
  };

  if ( !ram || !rom.data ) return;
  //
  for ( int k = 0; k < cmForm->pList->Items->Count; k++ )
  { //
    if ( cmForm->pList->Selected[ k ] )
    { //---------------------//
      // Draw the Kana First //
      //---------------------//
      // reset scrolling positions
      if ( !TxtForm->Active ) {
        textbox[0].Ypos = 0;
        textbox[1].Ypos = 0;
      }
      //
      DTT->Checked    = false;
      txt.ptr_index   = k;
      DrawText( false, map.height, map.width );
      // Get to the string Location
      sprintf( buf, ".STRING %d", k );
      //
      KanaForm->Caption = "Kana Text: String #" + IntToStr( k );
      // Disable the Main window
      Find1->FindText  = AnsiString( buf );

      if ( (LONG)Sender == 1 )
        Find1Find( (TObject *)1 );
      else
        Find1Find( NULL );
      //------------------------------//
      // Build translated text string //
      //------------------------------//
      if ( indexLine != -1 )
      { // Clear the buffer
        // copy text to temp buffer
        TxtForm->Memo1->Clear( );
        valu = 0;
        //
        while( Trim( TxtForm->TDMemo->Lines->Strings[ indexLine + valu ] ) != ".ENDS" )
          TxtForm->Memo1->Lines->Add( TxtForm->TDMemo->Lines->Strings[ indexLine + valu++ ] );
        //
        TxtForm->Memo1->Lines->Add( TxtForm->TDMemo->Lines->Strings[ indexLine + valu ] );
        //
        memset( EStr, 0, sizeof( EStr ) );
        inPosi = 0;
        //-------------------//
        //                   //
        //-------------------//
//        for ( int i = indexLine+1; i < TxtForm->TDMemo->Lines->Count; i++ )
        for ( int i = 1; i < TxtForm->Memo1->Lines->Count; i++ )
        { //
//          strcpy( buf, TxtForm->TDMemo->Lines->Strings[ i ].c_str( ) );
          strcpy( buf, TxtForm->Memo1->Lines->Strings[ i ].c_str( ) );
          sLen = strlen( buf );
          // Conversion Loop
          for ( int c = 0; c < sLen; c++ )
          { //-------------------------//
            // Check for control codes //
            //-------------------------//
            if ( buf[ c ] == '[' )
            { // Get to the code
              c++;
              c_test = 0;
              flag   = 0;
              while( codes[ c_test ][ 0 ] )
              { // Do some comparisons
                if ( !strncmpi( &buf[c], codes[ c_test ], strlen( codes[ c_test ] )) ) {
                  EStr[ inPosi++ ] = codes[ c_test + 1 ][0];
                  // Advance Testing DAta's curent position
                  c += strlen( codes[ c_test ] );
                  // If this is true, do NOT set the flag!
                  if ( buf[ c ] == '$' ) break;
                  // We found what we need! No more test
                  flag = 1;
                  // Decrementc since it's part of a FOR loop
//                  c--;
                  break;
                } // END IF
                //
                c_test += 2;
              }

              // If FLAG still zero, no code match was found!
              if ( !flag )
              { // Check for HEX Only codes
                if ( buf[c] == '$')
                { //
                  c++;
                  while( buf[c] != ']' ){
                    memcpy( conv, &buf[c], 2 ); conv[ 2 ] = 0;
                    EStr[ inPosi++ ] = strtol( conv, NULL, 16 );
                    c += 2;
                  }

                  //
                  EStr[ inPosi ] = STRING_END;
                }
                else
                { // If it comes here then it's regular data
                  EStr[ inPosi++ ] = buf[ --c ];
                  EStr[ inPosi   ] = STRING_END;
                }
              } // END IF

            } // END IF - Control Codes
            else
            { // regular text
              EStr[ inPosi++ ] = buf[ c ];
              EStr[ inPosi   ] = STRING_END;
            } // END IF - Everything else
          }

          // Add the Line Break if needed
          strcpy( buf, TxtForm->Memo1->Lines->Strings[ i + 1 ].c_str( ) );
          if ( !strncmpi( buf, ".ENDS", 5) ){
            EStr[ inPosi++ ] = TEXT_BREAK;
            EStr[ inPosi   ] = STRING_END;
            break;
          } else {
            EStr[ inPosi++ ] = LINE_BREAK;
            EStr[ inPosi   ] = STRING_END;
          }
        } // NEXT i

        //
        //
        DTT->Checked = true;
        DrawText( false, 16, 16 );
        DTT->Checked = false;
      }

      //
      sprintf( buf, "Offset: %06X | PTR: %04X -> %06X",
                    (lpTxtBlocks[ txt.posi ] & 0xFF8000) | txt.pntr,
                    txt.pntr,
                    txt.posi + (k << 1)
             );
      //
      StatusBar1->Panels->Items[0]->Text = AnsiString( buf );
      StatusBar1->Panels->Items[1]->Text = "Line {Kana, Ascii}: " + IntToStr( (textbox[0].Ypos >> 4) ) + ", " + IntToStr( (textbox[1].Ypos >> 4) );
      if ( Sender && (LONG)Sender != 1 && cmForm->Visible ) cmForm->pList->SetFocus( );
      break;
    }
  }
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::DecodeFont( LONG posi, BYTE *TILE )
{
  WORD valu;

  if ( rom.data && ram )
  { //
//    fseek( rf, Snes2Pc( 0x8C9C00 + (z << 1) ), SEEK_SET );
//    valu = readw( rf );
//    valu = WRAM( posi );

    // Decode the font
    LRAM( 0x1A ) = 0x10F4;
    LRAM( 0x1D ) = 0x10B4;
    //
    WRAM( 0x10AA ) = 0x0000;
    WRAM( 0x10AC ) = 0x0000;
    WRAM( 0x10AE ) = 0x0004;
    //
    WRAM( 0x10B0 ) = 0x0000;
    LRAM( 0x30 )   = posi;
    //
    reg.stack = 4;
    while( reg.stack > 0 )
    { //
      reg.y     = WRAM( 0x10AC );

      // Get to the font
  //    fseek( rf, LRAM( 0x30 ) + reg.y, SEEK_SET );
      ram[ 0x10B2 ] = rom.data[ LRAM( 0x30 ) + reg.y ];
      //
      reg.y++;
      WRAM( 0x10AC ) = reg.y;
      //
      reg.x = 8;
      while( reg.x > 0 )
      { // BIT set??
        if ( ram[ 0x10B2 ] & 1 )
        { //
          reg.y = WRAM( 0x10AE );
  //        fseek( rf, LRAM( 0x30 ) + reg.y, SEEK_SET );
          ram[ 0x10B0 ] = rom.data[ LRAM( 0x30 ) + reg.y ];
          reg.y++;
          WRAM( 0x10AE ) = reg.y;
        }

        // BIT clear
        reg.y = WRAM( 0x10AA );
        reg.a = ram[ 0x10B0 ];
        // Store the data
        ram[ WRAM(0x1A) + reg.y ] = reg.a;
        ram[ WRAM(0x1D) + reg.y ] = reg.a;
        reg.y++;
        WRAM( 0x10AA ) = reg.y;
        //
        reg.x--;
        ram[ 0x10B2 ] >>= 1;
      }// WEND

      reg.stack--;
    } // WEND - stack

    //
    memcpy( TILE, &ram[ WRAM(0x1D) ], 32 );

  } // pointer test
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::Find1Find(TObject *Sender)
{
/*  int  StartPos,
       ToEnd,
       curLine,
       indexLine;
*/
  // begin the search after the current selection
  // if there is one
  // otherwise, begin at the start of the text
  if ( TxtForm->TDMemo->SelLength )
    StartPos = TxtForm->TDMemo->SelStart + TxtForm->TDMemo->SelLength;
  else

    StartPos = 0;

  // ToEnd is the length from StartPos
  // to the end of the text in the rich edit control

  ToEnd   = TxtForm->TDMemo->Text.Length( ) - StartPos;

  FoundAt = TxtForm->TDMemo->FindText( Find1->FindText, StartPos, ToEnd, TSearchTypes( ) );
  //

  if ( FoundAt != -1 )
  {
//    TxtForm->TDMemo->SetFocus( );
    TxtForm->TDMemo->SelStart  = FoundAt;
    TxtForm->TDMemo->SelLength = 0;
    //
    curLine              = TxtForm->TDMemo->Perform( EM_GETFIRSTVISIBLELINE, 0, 0 );
    if ( TxtForm->TDMemo->Text.Length( ) > 0xFFFF )
      indexLine          = TxtForm->TDMemo->Perform( EM_EXLINEFROMCHAR, FoundAt, 0 );
    else
      indexLine          = TxtForm->TDMemo->Perform( EM_LINEFROMCHAR, FoundAt, 0 );
    //
//    TxtForm->TDMemo->Perform( EM_LINESCROLL, 0, indexLine - curLine );
    if ( (LONG)Sender != 1 )
      TxtForm->TDMemo->Perform( EM_LINESCROLL, 0, indexLine - curLine );
  }
  else
  {
    indexLine = -1;
  }
}


//---------------------------------//
//                                 //
//---------------------------------//
long __fastcall TmyForm::GetCurLine( long valu )
{
  DWORD both = 0;
  int indexLine;
  int indexLength;

  both        = MAKELPARAM( (valu >> 16) & 0xFFFF, (valu >> 0 ) & 0xFFFF );
  indexLine   = TxtForm->TDMemo->Perform( EM_LINEFROMCHAR, -1, 0 );
//  indexLength = (LOWORD(both)/8) + TxtForm->TDMemo->SelLength;

  return indexLine;
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::DisplayTextEditor1Click(TObject *Sender)
{
  TxtForm->Show( );
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::HideCodesClick(TObject *Sender)
{
  HideCodes->Checked ^= 1;
  // Kana
  DTT->Checked = false;
  DrawText( false, map.height, map.width );
  // Ascii
  DTT->Checked = true;
  DrawText( false, map.height, map.width );
  DTT->Checked = false;

/*  char *str[4] = { "Visible", "Hidden", "Inactive", "Active" };
  //
  HideCodes->Checked ^= 1;
  DrawText( false, map.height, map.width );
  //
  StatusBar1->Panels->Items[1]->Text = "Control Codes: " + AnsiString( str[ HideCodes->Checked & 1 ] ) + " | VWF: " + AnsiString( str[ (UseVWFRoutine1->Checked & 1) + 2 ] );
*/
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::UseVWFRoutine1Click(TObject *Sender)
{
  UseVWFRoutine1->Checked ^= 1;
  // Kana
  DTT->Checked = false;
  DrawText( false, map.height, map.width );
  // Ascii
  DTT->Checked = true;
  DrawText( false, map.height, map.width );
  DTT->Checked = false;

/*  char *str[4] = { "Visible", "Hidden", "Inactive", "Active" };
  //
  UseVWFRoutine1->Checked ^= 1;
  DrawText( false, map.height, map.width );
  //
  StatusBar1->Panels->Items[1]->Text = "Control Codes: " + AnsiString( str[ HideCodes->Checked & 1 ] ) + " | VWF: " + AnsiString( str[ (UseVWFRoutine1->Checked & 1) + 2 ] );
*/
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::DTTClick(TObject *Sender)
{
  DTT->Checked ^= true;
  //
//  if ( DTT->Checked )
  pListClick( Sender );
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::FormResize(TObject *Sender)
{
  //
  if ( isActive == false ) return;
  //
  if ( myForm->WindowState == wsNormal )
  {
    TxtForm->Top  = myForm->Top;
    TxtForm->Left = myForm->Left + myForm->Width + 2;
    //
    cmForm->Top  = TxtForm->Top + TxtForm->Height + 2;;
    cmForm->Left = TxtForm->Left;
    //
    if ( Sender != NULL )
    {
      KanaForm->Left = myForm->Left;
      KanaForm->Top  = myForm->Top + myForm->Height + 2;
    }
    else
    {
      KanaForm->Left = cmForm->Left;
      KanaForm->Top  = cmForm->Top + cmForm->Height + 2;
    }
  }
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::DefaultWindowSize1Click(TObject *Sender)
{
  if ( myForm->WindowState == wsMaximized )
    myForm->WindowState = wsNormal;
  //
  myForm->ClientHeight = WinY;
  myForm->ClientWidth  = WinX;
  //
  FormResize( myForm );
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::Red1Click(TObject *Sender)
{
  TMenuItem *m = (TMenuItem *)Sender;

  m->Checked = true;

  // Kana
  DTT->Checked = false;
  DrawText( false, map.height, map.width );
  // Ascii
  DTT->Checked = true;
  DrawText( false, map.height, map.width );
  DTT->Checked = false;
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::TEOnTopClick(TObject *Sender)
{
  TEOnTop->Checked ^= true;
  //
  if ( TEOnTop->Checked )
  {
    TxtForm->FormStyle = fsStayOnTop;
    KanaForm->FormStyle = fsStayOnTop;
  }
  else
  {
    TxtForm->FormStyle = fsNormal;
    KanaForm->FormStyle = fsNormal;
  }
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::ViewHexData1Click(TObject *Sender)
{
  HexForm->Show( );
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::ViewKanaTextDump1Click(TObject *Sender)
{
  KanaForm->Show( );
}

//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::Zoominx21Click(TObject *Sender)
{
  if ( myForm->WindowState == wsMaximized )
    myForm->WindowState = wsNormal;
  //
  myForm->ClientHeight = WinY + 256;
  myForm->ClientWidth  = WinX << 1;
  //
  FormResize( NULL );
}


//---------------------------------//
//                                 //
//---------------------------------//
void __fastcall TmyForm::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
  TBOX *myBox = NULL;

  if ( Shift.Contains( ssShift) ) myBox = &textbox[0];
  if ( Shift.Contains( ssCtrl ) ) myBox = &textbox[1];

  if ( myBox )
  {
    switch( Key )
    {
      case VK_UP  : if ( myBox->Ypos ) myBox->Ypos -= 16; else Key = 0; break;
      case VK_DOWN: if ( (myBox->Ypos + 96) < 0x300 ) myBox->Ypos += 16; else Key = 0; break;
      default     : Key = 0; break;
    }
  }

  // Kana
  if ( Key )
  {
    DTT->Checked = false;
    DrawText( false, map.height, map.width);

    // Ascii
    DTT->Checked = true;
    DrawText( false, map.height, map.width );
    DTT->Checked = false;
    //
//    StatusBar1->Panels->Items[1]->Text = "Kana line: " + IntToStr( (textbox[0].Ypos >> 4) ) + " | ASCII line: " + IntToStr( (textbox[1].Ypos >> 4) );
    StatusBar1->Panels->Items[1]->Text = "Line {Kana, Ascii}: " + IntToStr( (textbox[0].Ypos >> 4) ) + ", " + IntToStr( (textbox[1].Ypos >> 4) );
  }
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::VideoPaint(TObject *Sender)
{
  if ( rom.data )
    Video->Canvas->StretchDraw( Video->ClientRect, Vga );
}


//--------------------------------//
//                                //
//--------------------------------//
void __fastcall TmyForm::TableLoader( char *tblFile )
{
  char *tval;
  long val;
  char buf[0x100],
       tuf[256],
       *p,
       *d,
       c;
  FILE *tf;

  // Clear all tabl buffers
  tf = fopen( tblFile, "rt" );
  if ( !tf ){
    ShowMessage("Could not load the table file...");
    return;
  }// END IF

  _freeTBL( );

  //-----------------------//
  // Load the table file   //
  //-----------------------//
  while( fgets( buf, 255, tf ) )
  { // Clear line break characters
    if ( strchr( buf, '\n' ) ) buf[ strlen( buf ) - 1 ] = 0;

    // Regular table values
    if ( buf[2] == '=' )
    { //
      buf[2]         = 0;
      val            = strtoul( buf, NULL, 16 );
      //--------------------------//
      // Select the buffer to use //
      //--------------------------//      
      if ( strlen( &buf[3] ) >= 2 )
      {
        table.dte[val] = (BYTE *)malloc( strlen( &buf[3] ) + 1 );
        //
        if ( !table.dte[val] )
        { //
          ShowMessage( "Error Allocating Memory for the Table File..." );
          _freeTBL( );
          return;
        }
        // copy the string
        strcpy( table.dte[val], &buf[3] );
      }
      else
      {
        table.tbl[val] = (BYTE *)malloc( strlen( &buf[3] ) + 1 );;
        //
        if ( !table.tbl[val] )
        { //
          ShowMessage( "Error Allocating Memory for the Table File..." );
          _freeTBL( );
          return;
        }
        // copy the string
        strcpy( table.tbl[val], &buf[3] );
      }
      //
      continue;
    }

    //
		 if ( buf[4] == '=' )
    { // Double table values //
      buf[4]         = 0;
      val            = strtoul( buf, NULL, 16 ) & 0x00FF;
      table.dbl[val] = (BYTE *)malloc( strlen( &buf[5] ) + 1 );
      //
      if ( !table.dbl[val] )
      { //
        ShowMessage("Error Allocating Memory for the Table File...");
        _freeTBL( );
        return;
      }
      // copy the string
      memset( table.dbl[val], 0, strlen( &buf[5] ) );
      strcpy( table.dbl[val], &buf[5] );
    } // END IF - dbl
  }// WEND

  fclose( tf );
}// END IF


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::LoadTableFile1Click(TObject *Sender)
{
  Open1->Title      = "Open TABLE File";
  Open1->Filter     = "Table File | *.tbl";
  Open1->InitialDir = cur_dir;
  //
  if ( Open1->Execute( ) )
  { //
    strcpy( tblf, Open1->FileName.c_str( ) );
    //
    TableLoader( tblf );
  }
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::InsertCOMPRESSIONintoROM1Click(TObject *Sender)
{
  WORD POINTERS[0x0300];
  LONG cur_posi;
  char *buf = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";

  if ( !rom.data || !ram ) return;
  // This game requires a table file
  if ( !tblf[0] )
  { //
    ShowMessage( "Error: Must load a table file first!" );
    return;
  }

  //------------------------//
  // DTE compression        //
  //------------------------//
  for ( int  i = 0; i < (0xE0 - 0x80); i++ )
  { //
    memset( buf, 255, 8 );
    if ( table.dte[ i + 0x80 ] )
    {
      memcpy( buf, table.dte[ i + 0x80 ], strlen(table.dte[ i + 0x80 ]) );
      memcpy( &rom.data[ 0x7B00 + (i << 3) ], buf, 8 );
    }
    else
    {
      buf[0] = (0x80 + i) >> 4;
      buf[1] = (0x80 + i) >> 0;
      memcpy( &rom.data[ 0x7B00 + (i << 3) ], buf, 8 );
    }
  }

  //------------------------//
  // Dictionary compression //
  //------------------------//
  cur_posi = 0;
  for ( int  i = 0; i < 0x200; i++ )
  { //
    if ( table.dbl[ i ] )
    {
      POINTERS[ i ] = (cur_posi + 0xC400);
      memcpy( &rom.data[ 0x64400 + cur_posi ], table.dbl[ i ], strlen( table.dbl[ i ] ) );
      cur_posi    += strlen( table.dbl[ i ] );
      //
      rom.data[ 0x64400 + cur_posi ] = 0xFF;
      cur_posi++;
    }
    else
    {
      POINTERS[ i ] = (cur_posi + 0xC400);
      buf = "       \xFF";
      memcpy( &rom.data[ 0x64400 + cur_posi ], buf, strlen( buf ) );
      cur_posi    += strlen( buf );
    }
  }

  // Store the pointers
  memcpy( &rom.data[ 0x64000 ], POINTERS, 0x0400 );
  //
  ShowMessage( "Compression inserted successfully!" );
  rom.Modified = true;
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::SaveRomFile1Click(TObject *Sender)
{
  FILE *rf = NULL;

  if ( !rom.data || !ram ) return;
  //
  rf = fopen( romf, "wb" );
  if ( !rf )
  { //
    ShowMessage( "Fatal Error: Could not open ROM File for saving..." );
    return;
  }
  //
  fwrite( (rom.data - rom.Header), 1, (rom.Length + rom.Header), rf );
  fclose( rf );
  //
  if ( isActive )
    ShowMessage( "ROM File saved successfully!" );
  //
  rom.Modified = false;
}


//------------------------------------//
//                                    //
//------------------------------------//
void __fastcall TmyForm::Insert1Click(TObject *Sender)
{
  TPTR *pointer = NULL;
  TBUF temp;
  char buf[16];
  char string[1024];
  LONG ptr_posi,
       count,
       cur_posi,
       text_size;


  if ( !rom.data || !ram ) return;

  // This game requires a table file
  if ( !tblf[0] ){
    ShowMessage( "Error: Must load a table file first!" );
    return;
  }

  // Clear Error box
  InsertForm->ListBox1->Clear( );
  InsertForm->Show( );
  // Clear data
  ptrBox->Clear( );
  //
  InsertForm->CGauge1->MaxValue = txt.Max_ptrs;
  InsertForm->CGauge1->MinValue = 0;
  InsertForm->Caption = "Building Pointer Table...";
  // Load up pointers
  for ( int c = 0; c < txt.Max_ptrs; c++ )
  { //
    txt.pntr    = WGET( rom.data, Snes2Pc(lpTxtBlocks[txt.posi] + (c << 1)) );
    sprintf( buf, "%08X  %3d", Snes2Pc( (lpTxtBlocks[txt.posi] & 0xFF8000) | txt.pntr), c );
    ptrBox->Items->Add( buf );
    //
    InsertForm->CGauge1->Progress = c;
    CheckMSG( );
  }

  // Get memory
  count = ptrBox->Items->Count;
  (BYTE *)pointer = (BYTE *)malloc( count * sizeof(TPTR) );
  if ( !pointer )
  {
    ShowMessage(
      "Fatal Error: Could not acquire needed memory.\n"
      "             Closing program..."
    );
    //
    _free( pointer );
    Close( );
    return;
  }

  //----------------------------------//
  // Find END of TEXT if not declared //
  //----------------------------------//
  temp           = txt;
  //
  if ( !lpTxtMaxPos[ txt.posi ] )
  { // Save the current data
    txt.data   = 0;
    //
    sscanf( ptrBox->Items->Strings[ ptrBox->Items->Count-1 ].c_str( ), "%s %d", &buf, &txt.ptr_index );
    txt.pntr   = WGET( rom.data, Snes2Pc(txt.posi + (txt.ptr_index << 1)) );
    cur_posi   = Snes2Pc( (txt.posi & 0xFF8000) | txt.pntr);
    //
    // Get the last pointer and find the end of text
    count = 0;
    while( txt.TextBuf[ count ] != 0xFF && (cur_posi + count) < rom.Length )
      count++;
    //
    if ( (cur_posi + count) >= rom.Length )
    {
      ShowMessage(
        "Error: Could not find \"End of Text\"."
        "       You can manually set the \"End of Text\" like so"
        "       in the Format text file. \".ENDBLOCK $offset\"."
       );
       //
       _free( pointer );
       return;
    }
    //
    lpTxtMaxPos[ txt.posi ] = (cur_posi + count);
  }

  //---------------------------------------//
  // Translate the raw text to usable data //
  //---------------------------------------//
  InsertForm->Caption = "Converting Text...";
  //
  for ( int c = 0; c < ptrBox->Items->Count; c++ )
  { //
    InsertForm->CGauge1->Progress = c;
    CheckMSG( );
    //
    sscanf( ptrBox->Items->Strings[ c ].c_str( ), "%X %d", &cur_posi, &count );
    txt.pntr    = cur_posi;
    // Position in table to store POINTER
    pointer[ c ].Position = count;
    pointer[ c ].Length   = Text2Raw( count );
    // Make sure it's a valid pointer
    if ( !pointer[ c ].Length ){
      sprintf( EStr, "Error String: %3d\xff", c );
      pointer[ c ].Length = strlen( EStr );
    }
    //
    pointer[ c ].pointer  = Pc2Snes( txt.pntr ) & 0xFFFF;
    pointer[ c ].Buffer   = (BYTE *)malloc( pointer[ c ].Length );
    if ( !pointer[ c ].Buffer ){
      ShowMessage( "Fatal Error: Could not acquire needed memory. Closing..." );
      _free( pointer );
      Close( );
      return;
    }
    // Able to get memory
    memcpy( pointer[ c ].Buffer, EStr, pointer[ c ].Length );
    EStr[0] = 0;
  } // NEXT c

  //----------------------------//
  // Check and fix all pointers //
  // assign duplicates          //
  //----------------------------//
  InsertForm->Caption = "Sorting Pointers...";
  //
  for ( int c = 0; c < ptrBox->Items->Count; c++ )
  { //
    InsertForm->CGauge1->Progress = c;
    CheckMSG( );
    //
    for ( int i = 0; i < c; i++ ){
      if ( pointer[ c ].pointer == pointer[ i ].pointer ){
        // Save the duplicate pointer as a
        // pointer to the index in the list
        pointer[ c ].pointer = i;
        pointer[ c ].Length  = 0;
        _free( pointer[ c ].Buffer );
        break;
      }
    }
  }

  //----------------------------------//
  // Align pointers according to data //
  // to be stored                     //
  //----------------------------------//
  // Starting pointer value
  count     = pointer[ 0 ].pointer;
  text_size = 0;
  for ( int c = 0; c < ptrBox->Items->Count; c++ )
  { // Not a duplicate pointer
    if ( (pointer[ c ].pointer & 0x8000) )
    { //
      pointer[ c ].pointer = count;
      // Adjust the pointer
      count     += pointer[ c ].Length;
      text_size += pointer[ c ].Length;
    }
  }

  //----------------------------------//
  // Test to see if the data is small //
  // enough to store in the ROM       //
  //----------------------------------//
  if ( text_size <= ( lpTxtMaxPos[ txt.posi ] - lpTextStart[ txt.posi ] ) )
  { // Store all the text first,
    // Then replace all the pointers
    cur_posi = Snes2Pc( lpTextStart[ txt.posi ] );
    InsertForm->Caption = "Sorting Pointers...";
    //
    for ( int c = 0; c < ptrBox->Items->Count; c++ )
    { //
      InsertForm->CGauge1->Progress = c;
      CheckMSG( );
      // Is it a valid pointer or a duplicate?
      if ( (pointer[ c ].pointer & 0x8000) )
      { // write the text
        memcpy( &rom.data[ cur_posi ], pointer[ c ].Buffer, pointer[ c ].Length );
        cur_posi += pointer[ c ].Length;
        //------------ POINTER ------------
        ptr_posi  = (pointer[ c ].Position << 1) + Snes2Pc( lpTxtBlocks[ txt.posi ] );
        *(WORD *)&rom.data[ ptr_posi ] = pointer[ c ].pointer;
        //
        rom.Modified = true;
      }
      else
      { //------------ POINTER ------------
        ptr_posi  = (pointer[ c ].Position << 1) + Snes2Pc( lpTxtBlocks[ txt.posi ] );
        *(WORD *)&rom.data[ ptr_posi ] = pointer[ pointer[c].pointer ].pointer;
        rom.Modified = true;
      } // END IF
    }
    //
    ShowMessage( "All text was inserted successfully!" );
  }
  else
    ShowMessage( "ERROR: Text to insert larger than space available!\n"
                 "Space difference: " + IntToStr( text_size - (lpTxtMaxPos[ txt.posi ] - lpTextStart[ txt.posi ]) ) + " BYTES."
               );

  // Free all data and return
  txt = temp;
  //
  for ( int c = 0; c < ptrBox->Items->Count; c++ )
     _free( pointer[c].Buffer );
  //
  _free( pointer );
  //
}


//-------------------------------//
//                               //
//-------------------------------//
long __fastcall TmyForm::Text2Raw( int index )
{
  #define LINE_BREAK 0xFE
  #define TEXT_BREAK 0xFF
  #define STRING_END 0x00

  long valu,
       c_test,
       pos;
  WORD inPosi = 0,
       strLength;
  char buf[256],
       tuf[512];
  char conv[16],
       flag,
       *p1,
       *p2;

  char *ctrl [ ] =
  {
    "[NAME"   , "\xF4",
    "[CLRSCR]", "\xF5",
    "[KEY]"   , "\xF6",
    "[COLOR"  , "\xF7",
    "[PAUSE"  , "\xF8",
    "[CHOICE]", "\xFD",
    "\0"      , "\0"
  };


  //-------------------//
  //                   //
  //-------------------//
  sprintf( buf, ".STRING %d", index );
  //
  Find1->FindText  = AnsiString( buf );
  Find1Find( (TObject *)1 );
  //------------------------------//
  // Build translated text string //
  //------------------------------//
//  CheckMSG( );
  if ( indexLine != -1 )
  { // Clear the buffer
    // copy text to temp buffer
    TxtForm->Memo1->Clear( );
    valu = 1;  // skip ".STRING x" text
    //
    while( Trim( TxtForm->TDMemo->Lines->Strings[ indexLine + valu ] ) != ".ENDS" )
      TxtForm->Memo1->Lines->Add( TxtForm->TDMemo->Lines->Strings[ indexLine + valu++ ] );
    //
    // Add the compression
    Compress( TxtForm->Memo1 );
    //
    memset( EStr, 0, sizeof( EStr ) );
    inPosi = 0;
    //---------------------------//
    //                           //
    //---------------------------//
    for ( int i = 0; i < TxtForm->Memo1->Lines->Count; i++ )
    { //
      strcpy( buf, TxtForm->Memo1->Lines->Strings[ i ].c_str( ) );
      strLength = strlen( buf );
      // Conversion Loop
      for ( int c = 0; c < strLength; c++ )
      { //-------------------------//
        // Check for control codes //
        //-------------------------//
        c_test = 0;
        flag   = 0;
        //
        while( ctrl[ c_test ][ 0 ] )
        { // Do some comparisons
          if ( !strncmpi( &buf[c], ctrl[ c_test ], strlen( ctrl[ c_test ] )) ) {
             EStr[ inPosi++ ] = ctrl[ c_test + 1 ][0];
            // Advance Testing DAta's curent position
            c += strlen( ctrl[ c_test ] );
            // If this is true, do NOT set the flag!
            if ( buf[ c ] == '$' ){
              buf[ c - 1 ] = '[';
              c--;
              goto _GotCode;
            }
            // We found what we need! No more test
            flag = 1;
            break;
          } // END IF
          //
          c_test += 2;
        }

        //----------------------------//
        // Check for control codes #2 //
        //----------------------------//
        c_test = -1;
        flag   = 0;
        //
        while( ++c_test < 256 )
        { // Do some comparisons
          // Make sure the code exist
          if ( !codes[ c_test ].text )
            continue;
          //
          memset( tuf, 0, 256 );
          pos = -1;
          while( ++pos < codes[ c_test ].length ){
            if ( codes[ c_test ].text[ pos ] < 0x7F && codes[ c_test ].text[ pos ] > 0x1F )
              tuf[ pos ] = codes[ c_test ].text[ pos ];
            else {
              tuf[ pos ] = 0;
              break;
            }
          }

          //
          if ( pos && !strncmpi( &buf[c], tuf, strlen( tuf ))
             )
          { //
            EStr[ inPosi++ ] = c_test;
            // Advance Testing DAta's curent position
            c += strlen( tuf ) - 1;
            // If this is true, do NOT set the flag!
            if ( buf[ c ] == '$' ){
              buf[ c - 1 ] = '[';
              c--;
              break;
            }
            // We found what we need! No more test
            flag = 1;
            // Decrementc since it's part of a FOR loop
            break;
          } // END IF
          //
//          c_test++;
        }


        // A jump from first cntrol code test
        _GotCode:

        // If FLAG still zero, no code match was found!
        if ( !flag )
        { // Check for HEX Only codes
          if ( buf[c] == '[' && buf[c + 1] == '$')
          { //
            c += 2;
            while( buf[c] != ']' && c < strLength ){
              memcpy( conv, &buf[c], 2 ); conv[ 2 ] = 0;
              EStr[ inPosi++ ] = strtol( conv, NULL, 16 );
              c += 2;
            }
            //
            if ( c >= strLength )
            { //
//              InsertForm->Show( );
              sprintf( tuf, "Text: \"%s\", String Index: %d", buf, index );
//              ShowMessage( "Error: HEX-data read with no terminating \']\' character.\n" + AnsiString( tuf ) );
              InsertForm->ListBox1->Items->Add( "Error: HEX-data read error! - [ " + AnsiString( tuf ) + " ]");
            }
            //
            EStr[ inPosi ] = STRING_END;
          }
          else
          { // If it comes here then it's regular data
            EStr[ inPosi++ ] = buf[ c ];
            EStr[ inPosi   ] = STRING_END;
          }
        } // END IF

      } // END IF - Control Codes
      // Add the Line Break if needed
      EStr[ inPosi++ ] = LINE_BREAK;
      EStr[ inPosi   ] = STRING_END;
    } // NEXT i

    // Add the End of text data
    EStr[ inPosi++ ] = TEXT_BREAK;
    EStr[ inPosi   ] = STRING_END;
  }// END IF

  return inPosi;
}


//--------------------------------//
//                                //
//--------------------------------//
void __fastcall TmyForm::Compress(TObject *Sender)
{
  TRichEdit *myMemo = (TRichEdit *)Sender;

  // Add DICTIONARY compression
  for ( int  i = 0; i < 0x200; i++ )
  { //
    if ( table.dbl[ i ] )
    {
      StartPos = 0;
      ToEnd    = myMemo->Text.Length( ) - StartPos;
      FoundAt  = myMemo->FindText( AnsiString( table.dbl[i] ), StartPos, ToEnd, TSearchTypes( ) << stMatchCase );
      //
      if ( FoundAt != -1 )
      { // Replace with my data
        myMemo->SelStart  = FoundAt;
        myMemo->SelLength = AnsiString( table.dbl[i] ).Length( );
        myMemo->SelText   = "[$" + IntToHex( (0xE000 + i), 4 ) + "]";
        //
        i--;
      }
    }
  }

  // Add DTE compression
  for ( int  i = 0; i < 0x100; i++ )
  { //
    if ( table.dte[ i ] )
    {
      StartPos = 0;
      ToEnd    = myMemo->Text.Length( ) - StartPos;
      FoundAt  = myMemo->FindText( AnsiString( table.dte[i] ), StartPos, ToEnd, TSearchTypes( ) << stMatchCase );
      //
      if ( FoundAt != -1 )
      { // Replace with my data
        myMemo->SelStart  = FoundAt;
        myMemo->SelLength = AnsiString( table.dte[i] ).Length( );
        myMemo->SelText   = "[$" + IntToHex( i, 2 ) + "]";
        //
        i--;
      }
    }
  }
}


//-------------------------//
// IPS Patcher             //
//-------------------------//
void __fastcall TmyForm::PATCHRomFile1Click(TObject *Sender)
{
  char buf[260];
  FILE *tf,
       *f1;
  int  xx,
       k;

  if ( !rom.data || !ram ) return;
  //----------------------//
  // Patch the ROM file   //
  //----------------------//
  if ( rom.Modified )
  {
    k = Application->MessageBox( "Rom has been modified. Save these changes?",
                                 " IPS Patcher...", MB_YESNO + MB_ICONQUESTION);
    if ( k == ID_YES )
      SaveRomFile1Click( NULL );
    //  
  }
  //
  memset( &ips, 0, sizeof(TPAT) );

  Open1->Title      = "Select PATCH file(s)...";
  Open1->InitialDir = cur_dir;
  Open1->FileName   = "";
  Open1->Filter     = "IPS files (*.ips)|*.ips";
  Open1->Options    = Open1->Options << ofAllowMultiSelect;

  if ( Open1->Execute( ) )
  { //
    for ( int i = 0; i < Open1->Files->Count; i++ )
    {
      strcpy( ips.fil, Open1->Files->Strings[ i ].c_str( ) );
      tf = fopen( ips.fil, "rb" );
      _Error1:
      if ( !tf )
      { // make sure this is not pen
        ShowMessage( "File not found or is invalid. No patching performed.");
        Open1->Options = Open1->Options >> ofAllowMultiSelect;
        return;
      }
      //
      fclose( tf );

      //---------------------//
      //                     //
      //---------------------//
      // Start patching file
      tf = fopen( ips.fil, "rb" );
      f1 = fopen( "__temp__.qqq", "wb" );

      if ( !f1 || !tf ) goto _Error1;

      // Store current ROM data to the temp file
      fwrite( (rom.data - rom.Header), 1, (rom.Length + rom.Header), f1 );
      fclose( f1 );
      f1 = fopen( "__temp__.qqq", "r+b" );
      // Test file again
      if ( !f1 || !tf ) goto _Error1;

      ips.ofs = 0;
      ips.lof = FileSize( tf );         // get file length
      memset( buf, 0, 255 );
      fread( buf, 1, 5, tf );          // check for PATCH name tag
      // Validation check
      if ( strncmp( buf, "PATCH", 5 ) )
      { //
        fclose( tf );
        fclose( f1 ); //remove("__temp__.qqq");
        ShowMessage( "Not a valid \"PATCH\" file!" );
        Open1->Options = Open1->Options >> ofAllowMultiSelect;
        return;
      }// END IF

      //-------------------------//
      // Loop through the data   //
      //-------------------------//
      while( ftell( tf ) < ips.lof )
      { // get offset of data in ROM
        ips.ofs   = fgetc(tf);
        ips.ofs <<=16;
        ips.ofs  += ((WORD)fgetc(tf)<<8) + fgetc(tf);
        // check for EOF
        if ( ips.ofs == 0x454F46 ) break;

        // get size of data
        ips.sze = ((WORD)fgetc(tf)<<8) + fgetc(tf);

        // Check for RLE data
        if ( !ips.sze )
        { // we have RLE
          ips.sze = (WORD)(fgetc(tf)<<8) + fgetc(tf);  // get RLE size
          ips.dat = fgetc(tf);   // get RLE byte
          fseek(f1, ips.ofs, SEEK_SET);
          // Store the data
          while( ips.sze-- ) fputc( ips.dat, f1 );
        }
        else
        { // Regular data
          fseek(f1, ips.ofs, SEEK_SET);
          while( ips.sze-- ){
            xx = fgetc( tf );
            fputc( xx, f1 );
          }// WEND
        }// END IF

      }// WEND

      fclose( tf );
      rom.Length  = FileSize(f1);
      // free up current ROM data
      _free( rom.data );
      //
      rom.data = (char *)malloc( rom.Length );
      if ( !rom.data )
      { //
        fclose( f1 );
        remove("__temp__.qqq");
        Application->MessageBox( "Fatal Error: Could Not Allocate Memory for PATCHED File.\n"
                                 "Pogram will be shutdown.",
                                 "IPS Error",
                                 MB_OK + MB_ICONERROR
                               );
        //
        Close( );
        Open1->Options = Open1->Options >> ofAllowMultiSelect;
        return;
      }

      // Reload new rom data
      fseek( f1, 0, SEEK_SET );
      fread( rom.data, 1, rom.Length, f1 );
      fclose( f1 );
      remove( "__temp__.qqq" );
    }// NEXT - i

    //
    ShowMessage( "Patching is complete! Remember to SAVE the changes!" );
    rom.Modified   = true;
    Open1->Options = Open1->Options >> ofAllowMultiSelect;
    return;
  } // END IF
}


//-------------------------------//
//                               //
//-------------------------------//
void __fastcall TmyForm::DumpKanatoafile1Click(TObject *Sender)
{
  WORD pntr;
  BYTE *TxtBuf;
  FILE *tf;

  if ( !rom.data ) return;

  FSave->InitialDir = cur_dir;
  FSave->Title      = "Dump Working RAM to file...";
  FSave->FileName   = "";
  //
  if ( FSave->Execute( ) )
  { //
    tf = fopen( FSave->FileName.c_str( ), "wt" );
    if ( !tf ){
      ShowMessage( "Error: Could not open file for saving..." );
      return;
    }

    // Save the current lines first
    TxtForm->Memo1->Text = KanaForm->kanaEdit->Text;
    // Hide the text
    KanaForm->kanaEdit->Visible = false;

    //
    for ( int i = 0; i < cmForm->pList->Items->Count; i++ )
    { //
      pntr     = lpTxtPoints[ i ];
      TxtBuf   = &rom.data[ Snes2Pc( (lpTxtBlocks[ txt.posi ] & 0xFF8000) | pntr) ];
      //
      KanaForm->ShowText( TxtBuf, 0 );
      fprintf( tf, ".STRING %d\n", i );
//      viewKana->kanaMemo->Lines->Add( "\r\n" );
      //
      for ( int c = 0; c < KanaForm->kanaEdit->Lines->Count; c++ )
        fprintf( tf,"%s\n", KanaForm->kanaEdit->Lines->Strings[ c ].c_str( ) );
      //
      fprintf( tf, ".ENDS\n\n" );
    }

    // Restore the current lines
    KanaForm->kanaEdit->Text = TxtForm->Memo1->Text;
    // Show the form again
    KanaForm->kanaEdit->Visible = true;
    //
    fclose( tf );
    ShowMessage( "Text Data dumped to the file!" );
  }
}


//-------------------------------//
//                               //
//-------------------------------//
void __fastcall TmyForm::ViewKanaDump1Click(TObject *Sender)
{
  WORD pntr;
  BYTE *TxtBuf;

  if ( !rom.data ) return;

  viewKana->Show( );
  viewKana->kanaMemo->Visible = false;

  // Save the current lines first
  TxtForm->Memo1->Text = KanaForm->kanaEdit->Text;
  // Hide the text
  KanaForm->kanaEdit->Visible = false;
  viewKana->kanaMemo->Clear( );
  //
  for ( int i = 0; i < cmForm->pList->Items->Count; i++ )
  { //
    pntr     = lpTxtPoints[ i ];
    TxtBuf  = &rom.data[ Snes2Pc( (lpTxtBlocks[ txt.posi ] & 0xFF8000) | pntr) ];
    //
    KanaForm->ShowText( TxtBuf, 0 );
    viewKana->kanaMemo->Lines->Add( ".STRING " + AnsiString( i ) );
//    viewKana->kanaMemo->Lines->Add( "\r\n" );
    //
    for ( int c = 0; c < KanaForm->kanaEdit->Lines->Count; c++ )
      viewKana->kanaMemo->Lines->Add( KanaForm->kanaEdit->Lines->Strings[ c ] );
    //
    viewKana->kanaMemo->Lines->Add( ".ENDS" );
    viewKana->kanaMemo->Lines->Add( "\r\n\r\n" );
  }

  // Restore the current lines
  KanaForm->kanaEdit->Text = TxtForm->Memo1->Text;
  // Show the form again
  KanaForm->kanaEdit->Visible = true;
  viewKana->kanaMemo->Visible    = true;
}

